package com.elvin.zoe.template;

import static com.elvin.zoe.template.HtmlTemplateResources.chart;
import static com.elvin.zoe.template.HtmlTemplateResources.footGroupTemplate;
import static com.elvin.zoe.template.HtmlTemplateResources.headGroupTemplate;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Logger;

import com.elvin.zoe.pojo.CallMessage;
import com.elvin.zoe.pojo.Conversation;
import com.elvin.zoe.pojo.Message;
import com.elvin.zoe.pojo.structure.DatetimeRefiner;
import com.elvin.zoe.pojo.structure.MessageCount;
import com.elvin.zoe.pojo.structure.MessageGroup;
import com.elvin.zoe.pojo.structure.MessageOrganizer;
import com.elvin.zoe.util.Configurator;
import com.elvin.zoe.util.FileUtil;
import com.elvin.zoe.util.MessageGroupAnalyticsData;
import com.elvin.zoe.util.StringUtil;

public class MonthlyHtmlTemplate extends HtmlTemplate {

    private static Logger logger = Logger.getLogger(MonthlyHtmlTemplate.class);

    private final SimpleDateFormat dateFormatYyyyMm = new SimpleDateFormat("yyyyMM");
    private final SimpleDateFormat dateFormatMMMMMyyyy = new SimpleDateFormat("MMMMM, yyyy");
    private static final String linkPrefix = "sjp_";

    public MonthlyHtmlTemplate(Conversation conversation) {
        super(conversation);
    }

    public Map<String, String> generateMonthlyHtml(int messageNumberStart) throws ParseException, IOException {

        Collection<MessageGroup> monthlyMessageGroup = generateMessageGroupByMonth(messageNumberStart);

        List<MessageGroup> monthlyMessageGrouplist = new ArrayList<MessageGroup>(monthlyMessageGroup);
        Collections.sort(monthlyMessageGrouplist, new Comparator<MessageGroup>() {
            @Override
            public int compare(MessageGroup o1, MessageGroup o2) {
                return o1.getMessageGroupDate().compareTo(o2.getMessageGroupDate());
            }
        });

        String template = FileUtil.readFile(new File(Configurator.monthlyTemplateFile));

        MessageCount totalMessageCount = new MessageCount();
        for(MessageGroup messageGroup : monthlyMessageGroup){
            totalMessageCount.addCount(messageGroup.getMessageCount());
        }

        String menuFoot = getMessageCounts(totalMessageCount) + "<br>" + dateFormat.format(new Date());

        Map<String, String> mapFileName2PageContent = new TreeMap<String, String>();

        for(MessageGroup messageGroup : monthlyMessageGrouplist){

            Date messageGroupDate = messageGroup.getMessageGroupDate();
            String fileName = linkPrefix + dateFormatYyyyMm.format(messageGroupDate) + ".html";
            String page = template.replace("[TITLE.MONTH]", dateFormatMMMMMyyyy.format(messageGroupDate))
                                  .replace("[CONTENT.BODY]", generateBody(messageGroup))
                                  .replace("[MENU.FOOT]", menuFoot);

            mapFileName2PageContent.put(fileName, page);
        }

        return mapFileName2PageContent;

    }

    private String generateBody(MessageGroup monthMessageGroup){

        MessageCount messageCount = monthMessageGroup.getMessageCount();
        String messageCountsString = getMessageCounts(messageCount);

        MessageGroupAnalyticsData messageGroupAnalyticsData = StringUtil.getAnalyticsData(monthMessageGroup);

        int axisRange = StringUtil.getLastDayOfMonth(monthMessageGroup);
        String dataValue = StringUtil.getChartDataValue(monthMessageGroup);
        String dataScale = StringUtil.getChartDataScale(messageGroupAnalyticsData, monthMessageGroup);
        String dataValueMarker = StringUtil.getChartDataValueMarker(messageGroupAnalyticsData);

        logger.info("AxisRange - " + axisRange);
        logger.info("DataScale - " + dataScale);
        logger.info("DataValue - " + dataValue);
        logger.info("DataMarker - " + dataValueMarker);

        String chartString = chart.replace("[AXIS.RANGE]",  "0,1," + axisRange + ",1")
                                  .replace("[DATA.VALUE]", dataValue)
                                  .replace("[DATA.SCALE]", dataScale)
                                  .replace("[DATA.MARKER]", dataValueMarker)
                                  ;

        logger.info(chartString);

        String headGroupString = headGroupTemplate.replace("[MESSAGE.COUNTS]", messageCountsString)
                                                  .replace("[MESSAGE.CHART]", chartString)
                                                  .replace("[GROUP.HEAD.DATE]", dateFormatYyyyMm.format(monthMessageGroup.getMessageGroupDate()))
                                                  ;

        StringBuffer buf = new StringBuffer(headGroupString);

        Collection<MessageGroup> daylyMessageGrouplist = monthMessageGroup.getMessageGroups();
        for(MessageGroup messageGroup : daylyMessageGrouplist){
            List<Message> list = new ArrayList<Message>(messageGroup.getMessages());
            buf.append(generateDaylyGroupHtml(messageGroup.getMessageGroupDate(), list));
        }

        buf.append(footGroupTemplate);

        return buf.toString();

    }

    private Collection<MessageGroup> generateMessageGroupByMonth(int messageNumberStart) throws ParseException {

        List<Message> messages = conversation.getMessages();

        Collections.sort(messages, new Comparator<Message>() {
            @Override
            public int compare(Message o1, Message o2) {
                Date datetime1 = o1 instanceof CallMessage ? ((CallMessage)o1).getEndDatetime() : o1.getDateTime();
                Date datetime2 = o2 instanceof CallMessage ? ((CallMessage)o2).getEndDatetime() : o2.getDateTime();
                return datetime1.compareTo(datetime2);
            }
        });
        int messageNumber = messageNumberStart;
        for(Message message : messages){
            message.setMessageNumber(++messageNumber);
        }

        MessageOrganizer daylyMessageContainer = new MessageOrganizer("yyyy-MM-dd-EEE");
        daylyMessageContainer.setDatetimeRefiner(new DatetimeRefiner() {
            @Override
            public Date refine(Date date) {
                GregorianCalendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(Calendar.HOUR, -6);
                return calendar.getTime();
            }
        });
        daylyMessageContainer.addAllMessage(messages);
        logger.info("DaylyMessageContainer - MessageGroups - " + daylyMessageContainer.getMessageGroup().size());

        MessageOrganizer monthlyMessageContainer = new MessageOrganizer("yyyyMM");
        monthlyMessageContainer.addAllMessageGroup(daylyMessageContainer.getMessageGroup());
        logger.info("MonthlyMessageContainer - MessageGroups - " + monthlyMessageContainer.getMessageGroup().size());

        return monthlyMessageContainer.getMessageGroup();
    }


}
